using System;
using System.Collections.Generic;
using System.Text;

using NHibernate;
using NHibernate.Criterion;
using NHibernate.Classic;

using Castle.ActiveRecord;
using Castle.Core;

namespace Demo.Model
{
    [Serializable]
    public class AbstractActiveRecord<T> : AbstractActiveRecord
    {
        #region Generic ActiveRecord

        public static T Find(object id)
        {
            return (T)FindByPrimaryKey(typeof(T), id);
        }

        public static T FindOne()
        {
            return (T)ActiveRecordBase.FindFirst(typeof(T));
        }

        public static T[] FindAll()
        {
            return (T[])ActiveRecordBase.FindAll(typeof(T));
        }

        public static T[] FindAll(string orderBy)
        {
            Order[] orders = GetOrders(orderBy);
            return (T[])ActiveRecordBase.FindAll(typeof(T), orders);
        }

        public static T[] FindAll(params ICriterion[] criteria)
        {
            return (T[])ActiveRecordBase.FindAll(typeof(T), criteria);
        }

        public static T[] FindAll(Order[] orders, params ICriterion[] criteria)
        {
            return (T[])ActiveRecordBase.FindAll(typeof(T), orders, criteria);
        }

        public static T[] FindAll(DetachedCriteria detachedCriteria, params Order[] orders)
        {
            return (T[])ActiveRecordBase.FindAll(typeof(T), detachedCriteria, orders);
        }

        public static T[] SlicedFindAll(int from, int length, Order[] orders, ICriterion[] criteria) 
        {
            return (T[])ActiveRecordBase.SlicedFindAll(typeof(T), from, length, orders, criteria);
        }

        public static T[] FindAllByProperty(string propertyName, object propertyValue)
        {
            return (T[])ActiveRecordBase.FindAll(typeof(T), Expression.Eq(propertyName, propertyValue));
        }

        public static T[] FindAllByProperty(string propertyName, object propertyValue, string orderBy)
        {
            Order[] orders = GetOrders(orderBy);
            return (T[])ActiveRecordBase.FindAll(typeof(T), orders, Expression.Eq(propertyName, propertyValue));
        }

        public static T[] FindAllByPropertyLike(string likeProperty, string likeValue, int maxResults, string filterProperty, object filterPropertyValue)
        {
            Order[] order = new Order[] { Order.Asc("Description") };
            return (T[])ActiveRecordBase.SlicedFindAll(typeof(T), 0, maxResults, order, Expression.Eq(filterProperty, filterPropertyValue), Expression.Like(likeProperty, likeValue, MatchMode.Anywhere));
        }

        public static T[] FindAllByPropertyLike(string likeProperty, string likeValue, int maxResults)
        {
            Order[] order = new Order[] { Order.Asc("Description") };
            return (T[])ActiveRecordBase.SlicedFindAll(typeof(T), 0, maxResults, order, Expression.Like(likeProperty, likeValue, MatchMode.Anywhere));
        }

        public static int Count(params ICriterion[] criteria)
        {
            return ActiveRecordBase.Count(typeof(T), criteria);
        }

        protected static Order[] GetOrders(string orderBy)
        {
            var arrOrders = orderBy.Split(',');
            var orders = new Order[arrOrders.Length];

            for (int i = 0; i < arrOrders.Length; i++)
            {
                orders[i] = Order.Asc(arrOrders[i].Trim());
            }

            return orders;
        }

        #endregion
    }
}
